package com.api.syh56.shengyunhui.task;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nls.client.AccessToken;
import com.alibaba.nls.client.protocol.NlsClient;
import com.api.syh56.shengyunhui.common.Constants;
import com.api.syh56.shengyunhui.entity.*;
import com.api.syh56.shengyunhui.entity.common.ApiArea;
import com.api.syh56.shengyunhui.entity.common.ApiAreaDb;
import com.api.syh56.shengyunhui.mapper.ApiAreaDbMapper;
import com.api.syh56.shengyunhui.properties.AliOssProperties;
import com.api.syh56.shengyunhui.properties.AliSpeechProperties;
import com.api.syh56.shengyunhui.service.*;
import com.api.syh56.shengyunhui.util.HttpUtil;
import com.api.syh56.shengyunhui.util.LocationUtils;
import com.api.syh56.shengyunhui.websocket.ChatServer;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 定时任务类，定时处理订单状态
 */
@Component
@Slf4j
public class CommonTask {


    @Autowired
    private WayBillService wayBillService;

    @Autowired
    private TmpAddressService tmpAddressService;

    @Autowired
    private UserService userService;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private QuoteService quoteService;

    @Autowired
    private SystemMessageService systemMessageService;

    @Autowired
    private AliOssProperties aliOssProperties;

    @Autowired
    private AliSpeechProperties aliSpeechProperties;

    @Autowired
    private NlsClient nlsClient;

    @Autowired
    private ChatServer chatServer;

    @Autowired
    private CouponDetService couponDetService;

    @Autowired
    private PayInfoService payInfoService;

    @Autowired
    private RoutesService routesService;

    private static final String FOLDER_PATH_BASE = "D:\\wwwroot\\www.syh56.com\\wwwroot\\audio";
    /**
     * websocket测试
     */
//    @Scheduled(cron = "0 * * * * ? ") //每分钟触发一次
    @Scheduled(cron = "*/10 * * * * *") // 每五秒触发一次
    public void processTimeoutOrder(){
//        log.info("定时处理超时订单：{}", LocalDateTime.now());

//        System.out.println("https://www.syh56.com/audio/20240729172452.mp3" + LocalDateTime.now());
//        chatServer.broadcast("https://www.syh56.com/audio/20240729172452.mp3");

        chatServer.getList().forEach(uid -> {
            log.info("uid:" + uid);
//            chatServer.sendToUser(Long.valueOf(uid),"https://www.syh56.com/audio/20240729172452.mp3");;
        });
        System.out.println("routeTab");
        chatServer.getRoutetab().forEach((k,v) -> {
            log.info("k:" + k);
            log.info("v:" + v);
        });
    }

    /**
     * 项目启动时立即获取AccessToken，然后每隔24小时获取一次。
     */
    @Scheduled(initialDelay = 0, fixedRate = 86400000) // 初始延迟0毫秒，之后每隔86400000毫秒（24小时）执行一次
    public void fetchAccessToken() throws IOException {
        // 这里实现获取AccessToken的逻辑
        AccessToken accessToken = new AccessToken(aliOssProperties.getAccessKeyId(), aliOssProperties.getAccessKeySecret());
        accessToken.apply();
        aliSpeechProperties.setToken(accessToken.getToken());
        long expireTime = accessToken.getExpireTime()*1000L;
        log.info("aliSpeechProperties.getToken():" + aliSpeechProperties.getToken());
        ZoneId zoneId = ZoneId.of("Asia/Shanghai"); // 指定时区
        LocalDateTime dateTime = Instant.ofEpochMilli(expireTime).atZone(zoneId).toLocalDateTime();
        log.info("expireTime:" + dateTime);
        nlsClient.setToken(accessToken.getToken());
    }


    /**
     * 每隔3600秒（1小时）检查一次，如果超过24小时未发货的订单，则发送消息提示
     */
//    @Scheduled(initialDelay = 0, fixedRate = 10800000) // 初始延迟0毫秒，之后每隔（1小时）3600000执行一次3小时10800000
    @Scheduled(cron = "0 30 20 * * ?") // 每天晚上20:30
    public void WaybillJianCha() {
        QueryWrapper<Waybill> waybillQueryWrapper = new QueryWrapper<>();
        waybillQueryWrapper.lambda()
//                .between(Waybill::getQuoteTime, LocalDateTime.now().minusHours(24), LocalDateTime.now().minusHours(6))
                .eq(Waybill::getDeliveryStatus, Constants.DeliveryStatus.AWAIT_LOAD);
        List<Waybill> waybills = wayBillService.list(waybillQueryWrapper);

        for (Waybill waybill : waybills) {
            systemMessageService.SendMessageToDriverWhenTimeout(waybill);
        }
    }

    /**
     * 每隔3600秒检查一次，如果超过24小时未付款的订单，则更运单状态为取消
     */
    @Scheduled(initialDelay = 0, fixedRate = 3600000)
    public void waybillState(){
        UpdateWrapper<Waybill> waybillUpdateWrapper = new UpdateWrapper<>();
        waybillUpdateWrapper.lambda()
                .eq(Waybill::getWaybillStatus,Constants.WaybillStatus.AWAIT_QUOTE)
                .lt(Waybill::getCreationTime,LocalDateTime.now().minusHours(24))
                .set(Waybill::getWaybillStatus,Constants.WaybillStatus.CANCELLED);
        wayBillService.update(waybillUpdateWrapper);
        log.info("开始删除已取消状态超过48小时运单!");
        QueryWrapper<Waybill> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Waybill::getWaybillStatus,Constants.WaybillStatus.CANCELLED)
                .lt(Waybill::getLastModificationTime,LocalDateTime.now().minusHours(24));
        wayBillService.list(wrapper).forEach(waybill ->
                wayBillService.deleteWaybill(waybill.getId()));
        quoteService.getQuo();
    }

    @Scheduled(initialDelay = 0,fixedRate = 30000)
    public void updateWaybillState(){
        QueryWrapper<Waybill> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Waybill::getWaybillLock,Constants.WayBillLock.LOCK)
                .lt(Waybill::getPayTime,LocalDateTime.now().minusMinutes(10));
        wayBillService.list(wrapper).forEach(waybill -> {
            Short wayBillLock;
            if (Constants.PayMethod.PAY_NOW.equals(waybill.getPayMethod())) {
                wayBillLock = Constants.WaybillStatus.DEPOSIT_PAID.equals(waybill.getWaybillStatus()) ?
                        Constants.WayBillLock.LOCK : Constants.WayBillLock.UNLOCK;
            }else {
                wayBillLock = Constants.WaybillStatus.SETTLED.equals(waybill.getWaybillStatus()) ?
                        Constants.WayBillLock.LOCK : Constants.WayBillLock.UNLOCK;
            }
            waybill.setWaybillLock(wayBillLock);
            wayBillService.updateById(waybill);
            CouponDet couponDet = couponDetService.getById(waybill.getCuoId());
            if (couponDet != null){
                couponDet.setCouLock(Constants.WayBillLock.UNLOCK);
                couponDetService.updateById(couponDet);
            }
        });
    }



    @Scheduled(initialDelay = 0,fixedRate = 3600000)
    public void dropCancelledQuo(){
        QueryWrapper<Quote> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                        .eq(Quote::getStatus,Constants.QuoteStatus.IN_PROGRESS)
                        .lt(Quote::getLastModificationTime,LocalDateTime.now().minusHours(24));
        quoteService.list(wrapper).forEach(quote -> {
            quoteService.deleteQuote(quote.getId());
        });
    }


    /**
     * 运单发出每隔15/30分钟未报价发一次推送消息到专线用户
     */
    @Scheduled(initialDelay = 0,fixedRate = 600000)
    public void sendMessage(){
        QueryWrapper<Waybill> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Waybill::getWaybillStatus,Constants.WaybillStatus.AWAIT_QUOTE)
                .lt(Waybill::getCreationTime,LocalDateTime.now().minusMinutes(15));
        //获取未改变状态的运单
        wayBillService.list(wrapper).forEach(waybill -> {
            Integer sendTimes = waybill.getSendTimes();
            if (sendTimes == 0) {
                systemMessageService.SendMessageToDriverTimeOut(waybill);
                sendTimes += 1;
                waybill.setSendTimes(sendTimes);
                wayBillService.updateById(waybill);
            }
        });
//        QueryWrapper<Waybill> wayBillWrapper = new QueryWrapper<>();
//        wayBillWrapper.lambda()
//                .eq(Waybill::getWaybillStatus,Constants.WaybillStatus.AWAIT_QUOTE)
//                .lt(Waybill::getCreationTime,LocalDateTime.now().minusMinutes(30));
//        wayBillService.list(wayBillWrapper).forEach(waybill -> {
//            Integer sendTimes = waybill.getSendTimes();
//            if (sendTimes == 1) {
//                systemMessageService.SendMessageToDriverTimeOut(waybill);
//                sendTimes += 1;
//                waybill.setSendTimes(sendTimes);
//                wayBillService.updateById(waybill);
//            }
//        });
    }

    /**
     * 每隔3600秒（1小时）检查一次，货车即将到达目的地，短信提示货主和专线示
     */
    @Scheduled(initialDelay = 0, fixedRate = 1800000) // 初始延迟0毫秒，之后每隔（1小时）3600000 执行一次3小时10800000
    public void waybillCarSearch() {
        QueryWrapper<Waybill> waybillQueryWrapper = new QueryWrapper<>();
        waybillQueryWrapper.lambda()
                .eq(Waybill::getDeliveryStatus, Constants.DeliveryStatus.TRANSPORTING);

        List<Waybill> waybills = wayBillService.list(waybillQueryWrapper);

        for (Waybill waybill : waybills) {
            System.out.println(waybill.getCarNumber());
            Map<String, Object> stringObjectMap = wayBillService.waybillCarSearch(waybill);
            System.out.println(stringObjectMap);
            double lon = (double) stringObjectMap.get("lon");
            double lat = (double) stringObjectMap.get("lat");
            //计算发货市和收货市经纬度的总路程
            Long receiveAddressId = waybill.getReceiveAddressId();
            TmpAddress receiveAddress = tmpAddressService.getById(receiveAddressId);
            String receiveAddressLocation = receiveAddress.getAddressLocation();
            // 解析经纬度字符串
            double[] receiveLocation = LocationUtils.parseLocation(receiveAddressLocation);
            // 计算距离
            double distance = LocationUtils.calculateDistance(lon, lat,
                    receiveLocation[0], receiveLocation[1]);
            log.info("Total Distance: " + distance + " km");

            Long shipAddressId = waybill.getShipAddressId();
            TmpAddress shipAddress = tmpAddressService.getById(shipAddressId);

            Long shiperId = waybill.getShiperId();
            User shiper = userService.getById(shiperId);
            Long driverId = waybill.getDriverId();
            User driver = userService.getById(driverId);

            if (distance < 30) {

//                systemMessageService.sendSmsMessage(shiper.getUserName(), shipAddress.getCity(), receiveAddress.getCity(),
//                        "即将到达", driver.getUserName(), waybill.getCarNumber());
//                systemMessageService.sendSmsMessage(driver.getUserName(), shipAddress.getCity(), receiveAddress.getCity(),
//                        "即将到达", shiper.getUserName(), waybill.getCarNumber());
                systemMessageService.sendSmsReceiveMessage(shiper.getUserName(), waybill.getWaybillNumber(), shipAddress.getCity(), receiveAddress.getCity(),"即将到达", waybill.getCarNumber());
                systemMessageService.sendSmsReceiveMessage(driver.getUserName(), waybill.getWaybillNumber(), shipAddress.getCity(), receiveAddress.getCity(),"即将到达", waybill.getCarNumber());


            }

        }
    }







    //每天凌晨三点执行一次
    @Scheduled(cron = "0 0 3 * * ?")
    public void removeAlreadyCancledWaybill() {
        QueryWrapper<Waybill> waybillQueryWrapper = new QueryWrapper<>();
        waybillQueryWrapper.lambda().eq(Waybill::getWaybillStatus, Constants.WaybillStatus.CANCELLED);
        List<Waybill> list = wayBillService.list(waybillQueryWrapper);
        LocalDateTime now = LocalDateTime.now();
        for (Waybill waybill : list) {
            LocalDateTime creationTime = waybill.getCreationTime();
            // 判断是否超过7天
            if (creationTime.plusDays(7).isBefore(now)) {
                wayBillService.removeById(waybill);
                Long goodsId = waybill.getGoodsId();
                Long shipAddressId = waybill.getShipAddressId();
                Long receiveAddressId = waybill.getReceiveAddressId();

                if (goodsService.getById(goodsId) != null){
                    goodsService.removeById(goodsId);
                }
                if (tmpAddressService.getById(shipAddressId) != null){
                    tmpAddressService.removeById(shipAddressId);
                }
                if (tmpAddressService.getById(receiveAddressId) != null){
                    tmpAddressService.removeById(receiveAddressId);
                }
                QueryWrapper<Quote> quoteQueryWrapper = new QueryWrapper<>();
                quoteQueryWrapper.lambda().eq(Quote::getWaybillId, waybill.getId());
                quoteService.remove(quoteQueryWrapper);

                System.out.println("删除运单号"+waybill.getId());
            }
        }
    }


    // 项目启动时立即创建当天的文件夹
    @Scheduled(initialDelay = 0) // 立即执行，之后不重复执行
    public void createFolderOnStartup() {
        createFolder(0);
    }


    // 创建第二天文件夹的定时任务
    // 这里设置为午夜11点59分，确保在12点之前创建文件夹
    @Scheduled(cron = "59 59 23 * * ?")
    public void createFolderForNextDay() {
        createFolder(0);
        createFolder(1);
    }

    // 删除当天文件夹的定时任务
    // 这里设置为午夜0点，确保在新的一天开始时删除前天的文件夹
    @Scheduled(cron = "0 0 0 * * ?")
    public void deleteFolderForCurrentDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -2);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String currentDate = dateFormat.format(calendar.getTime());
        String currentDayFolderPath = FOLDER_PATH_BASE + "\\" + currentDate;

        deleteFolder(currentDayFolderPath);
    }

    private void createFolder(Integer plusDay) {
        //创建文件夹
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, plusDay);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String folderName = dateFormat.format(calendar.getTime());
        String DayFolderPath = FOLDER_PATH_BASE + "\\" + folderName;

        File folder = new File(DayFolderPath);
        if (folder.exists()) {
            System.out.println("文件夹已存在: " + DayFolderPath);
        } else if (folder.mkdirs()) {
            System.out.println("文件夹创建成功: " + DayFolderPath);
        } else {
            System.err.println("文件夹创建失败: " + DayFolderPath);
        }
    }

    private void deleteFolder(String folderPath) {
        File folder = new File(folderPath);
        if (!folder.exists()) {
            System.out.println("文件夹不存在，无需删除: " + folderPath);
            return;
        }

        deleteDirectory(folder);
        if (folder.exists()) {
            System.err.println("文件夹删除失败: " + folderPath);
        } else {
            System.out.println("文件夹删除成功: " + folderPath);
        }
    }

    private void deleteDirectory(File directory) {
        if (directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    deleteDirectory(file);
                }
            }
        }
        directory.delete();
    }

}
